"""
动作执行器
负责将智能体生成的动作转换为具体的单位操作

作者：wjttdbx
版本：3.0 - 重构版本
"""
import math
import numpy as np
from typing import List, Optional, TYPE_CHECKING

from .base_agent import AgentAction
from sh15.core.DroneManager import DroneManager
from sh15.core.LockingSystem import LockingSystem

if TYPE_CHECKING:
    from sh15.core.units import WhiteBoat, WhiteDrone
    from sh15.core.CoreEnvironment import CoreEnvironment


class ActionExecutor:
    """
    动作执行器
    
    负责将智能体的抽象动作转换为具体的单位操作和环境交互
    """
    
    def __init__(self):
        """初始化动作执行器"""
        self.drone_manager = DroneManager()
        self.debug_mode = False
        
    def execute_actions(self, action: AgentAction, white_boats: List['WhiteBoat'], 
                       white_drones: List['WhiteDrone'], core_env: 'CoreEnvironment',
                       current_time: float, dt: float):
        """
        执行智能体动作
        
        Args:
            action: 智能体生成的动作
            white_boats: 白方无人艇列表
            white_drones: 白方无人机列表
            core_env: 核心环境对象
            current_time: 当前时间
            dt: 时间步长
        """
        # 执行无人艇动作
        self._execute_boat_actions(action.get_boat_actions(), white_boats, core_env, current_time, dt)
        
        # 执行无人机动作
        drone_actions = action.get_drone_actions()
        if drone_actions.size > 0:
            self._execute_drone_actions(drone_actions, white_drones, white_boats, core_env, current_time, dt)
    
    def _execute_boat_actions(self, boat_actions: np.ndarray, white_boats: List['WhiteBoat'], 
                             core_env: 'CoreEnvironment', current_time: float, dt: float):
        """
        执行无人艇动作
        Args:
            boat_actions: 形状为 (5, 3) 的无人艇动作数组 [速度, 方向, lock_id]
            white_boats: 白方无人艇列表
            core_env: 核心环境对象
            current_time: 当前时间
            dt: 时间步长
        """
        for i, boat in enumerate(white_boats):
            if not boat.active or boat.is_frozen(current_time) or i >= len(boat_actions):
                continue
            # 解析动作
            speed, heading, lock_id = boat_actions[i]
            # 执行移动
            boat.move_with_kinematics(speed, heading, dt)
            # 执行锁定 - 使用lock_id作为目标的unit_id
            if lock_id >= 0:  # lock_id >= 0 表示要锁定指定unit_id的目标
                # 在调用前获取目标的锁定次数，用于识别“成功锁定”事件
                target = None
                prev_locked_times = None
                prev_active = None
                try:
                    for b in core_env.black_boats:
                        if b.id == int(lock_id):
                            target = b
                            prev_locked_times = getattr(b, 'locked_times', None)
                            prev_active = getattr(b, 'active', None)
                            break
                except Exception:
                    target = None

                success = LockingSystem.try_white_boat_lock(boat, int(lock_id), current_time)

                # 判断是否发生了成功锁定：locked_times 递增
                if target is not None and prev_locked_times is not None:
                    try:
                        if getattr(target, 'locked_times', prev_locked_times) > prev_locked_times:
                            core_env.white_lock_count += 1
                            # 若本次成功导致目标被消灭（active 从 True 变为 False），累计拦截数
                            if prev_active is True and getattr(target, 'active', True) is False:
                                core_env.intercepted_black_boats += 1
                                # 同帧广播清理：所有仍在锁定该目标的白艇立即停止锁定，避免残留状态
                                for wb in white_boats:
                                    try:
                                        if wb.current_target is not None and wb.current_target.id == int(lock_id):
                                            wb.stop_locking()
                                    except Exception:
                                        pass
                            if self.debug_mode:
                                print(f"[ActionExecutor] 计数: 白方成功锁定次数+1 (boat={boat.id}, target=B{int(lock_id)})")
                    except Exception:
                        pass
                if self.debug_mode and success:
                    print(f"[ActionExecutor] 无人艇{boat.id}锁定目标{int(lock_id)}开始")
                elif self.debug_mode and not success:
                    print(f"[ActionExecutor] 无人艇{boat.id}锁定目标{int(lock_id)}失败")
            else:  # lock_id < 0 表示不锁定任何目标
                core_env.stop_white_boat_lock(boat.id)
                if self.debug_mode:
                    print(f"[ActionExecutor] 无人艇{boat.id}停止锁定")
    
    def _execute_drone_actions(self, drone_actions: np.ndarray, white_drones: List['WhiteDrone'], 
                              white_boats: List['WhiteBoat'], core_env: 'CoreEnvironment', 
                              current_time: float, dt: float):
        """
        执行无人机动作
        Args:
            drone_actions: 形状为 (N, 3) 的无人机动作数组 [速度, 方向, drone_action]
            white_drones: 白方无人机列表
            white_boats: 白方无人艇列表
            core_env: 核心环境对象
            current_time: 当前时间
            dt: 时间步长
        """
        # 处理所有无人机（包括停靠在母舰上的无人机）
        for i, drone in enumerate(white_drones):
            if i >= len(drone_actions):
                continue
            drone_action = drone_actions[i]
            speed, heading, drone_action_value = drone_action[0], drone_action[1], drone_action[2]
            
            # 只有飞行中的无人机才执行移动
            if drone.state in ["flying", "returning"]:
                drone.move_with_kinematics(speed, heading, dt)
            
            # 处理无人机控制（起飞/降落）
            if drone_action_value < 0.5:  # drone_action < 0.5 表示降落/停靠
                if drone.state == "flying":
                    drone.state = "returning"
                    if self.debug_mode:
                        print(f"[ActionExecutor] 无人机{drone.id}开始返航")
                elif drone.state == "returning":
                    # 降落策略选择：根据drone_action_value的值决定降落策略
                    # drone_action_value < 0.25: 降落到起飞的母舰
                    # drone_action_value >= 0.25: 降落到最近的母舰
                    if drone_action_value < 0.25:
                        # 策略1：降落到起飞的母舰
                        target_boat = self._find_parent_boat_for_landing(drone, white_boats, current_time)
                        if target_boat:
                            success = self.drone_manager.land_drone(target_boat, drone, current_time)
                            if self.debug_mode:
                                if success:
                                    print(f"[ActionExecutor] 无人机{drone.id}成功降落到起飞的母舰{target_boat.id}")
                                else:
                                    print(f"[ActionExecutor] 无人机{drone.id}降落到起飞的母舰{target_boat.id}失败")
                        else:
                            if self.debug_mode:
                                print(f"[ActionExecutor] 无人机{drone.id}的起飞母舰不可用，尝试降落到最近的母舰")
                            # 如果起飞母舰不可用，降落到最近的母舰
                            target_boat = self._find_nearest_available_boat_for_landing(drone, white_boats, current_time)
                            if target_boat:
                                success = self.drone_manager.land_drone(target_boat, drone, current_time)
                                if self.debug_mode:
                                    if success:
                                        print(f"[ActionExecutor] 无人机{drone.id}成功降落到最近的母舰{target_boat.id}")
                                    else:
                                        print(f"[ActionExecutor] 无人机{drone.id}降落到最近的母舰{target_boat.id}失败")
                    else:
                        # 策略2：降落到最近的母舰
                        target_boat = self._find_nearest_available_boat_for_landing(drone, white_boats, current_time)
                        if target_boat:
                            success = self.drone_manager.land_drone(target_boat, drone, current_time)
                            if self.debug_mode:
                                if success:
                                    print(f"[ActionExecutor] 无人机{drone.id}成功降落到最近的母舰{target_boat.id}")
                                else:
                                    print(f"[ActionExecutor] 无人机{drone.id}降落到最近的母舰{target_boat.id}失败")
            else:  # drone_action >= 0.5 表示起飞/飞行
                # 处理返航状态：继续飞行
                if drone.state == "returning":
                    drone.state = "flying"
                    if self.debug_mode:
                        print(f"[ActionExecutor] 无人机{drone.id}继续飞行")
                
                # 处理充电状态：尝试起飞
                elif drone.state == "recharging" and drone_action_value >= 0.5:
                    if self.debug_mode:
                        print(f"[ActionExecutor] 无人机{drone.id}尝试起飞，停靠母舰ID: {drone.docked_on_boat_id}")
                    
                    # 检查无人机是否确实停靠在某艘母舰上
                    if drone.docked_on_boat_id >= 0:
                        success = core_env.launch_drone(drone.docked_on_boat_id)
                        if self.debug_mode:
                            if success:
                                print(f"[ActionExecutor] 无人艇{drone.docked_on_boat_id}成功发射无人机{drone.id}")
                            else:
                                print(f"[ActionExecutor] 无人艇{drone.docked_on_boat_id}发射无人机{drone.id}失败")
                    else:
                        if self.debug_mode:
                            print(f"[ActionExecutor] 无人机{drone.id}未停靠在任何母舰上，无法起飞")
                
                # 处理飞行状态：保持飞行（不需要特殊处理，因为已经在执行移动）
                elif drone.state == "flying":
                    if self.debug_mode:
                        print(f"[ActionExecutor] 无人机{drone.id}保持飞行状态")
    
 
    def set_debug_mode(self, enabled: bool):
        """设置调试模式"""
        self.debug_mode = enabled
        self.drone_manager.debug_mode = enabled
    
    def _find_nearest_available_boat_for_landing(self, drone: 'WhiteDrone', white_boats: List['WhiteBoat'], current_time: float) -> Optional['WhiteBoat']:
        """找到最近的、可用的降落母舰"""
        available_boats = [
            boat for boat in white_boats 
            if boat.active and not boat.is_frozen(current_time)
        ]
        
        if not available_boats:
            return None
        
        # 找到距离最近的可用母舰
        return min(available_boats, key=lambda boat: drone.distance_to(boat))
    
    def _find_parent_boat_for_landing(self, drone: 'WhiteDrone', white_boats: List['WhiteBoat'], current_time: float) -> Optional['WhiteBoat']:
        """找到无人机的起飞母舰（如果可用）"""
        # 查找无人机的起飞母舰
        for boat in white_boats:
            if boat.id == drone.parent_boat_id and boat.active and not boat.is_frozen(current_time):
                return boat
        return None





class SmartActionExecutor(ActionExecutor):
    """
    智能动作执行器
    
    扩展基础执行器，添加智能优化和自动调整功能
    """
    
    def __init__(self):
        super().__init__()
        self.action_history = []
        self.performance_tracker = {}
        
    def execute_actions(self, action: AgentAction, white_boats: List['WhiteBoat'], 
                       white_drones: List['WhiteDrone'], core_env: 'CoreEnvironment',
                       current_time: float, dt: float):
        """智能执行动作，包含优化和调整"""
        # 记录动作历史
        self._record_action(action, current_time)
        
        # 执行基础动作
        super().execute_actions(action, white_boats, white_drones, core_env, current_time, dt)
        
        # 执行智能优化
        self._apply_smart_optimizations(white_boats, white_drones, current_time, dt)
        
        # 更新性能追踪
        self._update_performance_tracking(white_boats, white_drones, current_time)
    
    def _record_action(self, action: AgentAction, current_time: float):
        """记录动作历史"""
        action_record = {
            'time': current_time,
            'boat_actions': action.get_boat_actions().copy(),
            'drone_actions': action.get_drone_actions().copy(),
            
        }
        self.action_history.append(action_record)
        
        # 限制历史记录长度
        if len(self.action_history) > 1000:
            self.action_history = self.action_history[-500:]
    
    def _apply_smart_optimizations(self, white_boats: List['WhiteBoat'], 
                                  white_drones: List['WhiteDrone'], current_time: float, dt: float):
        """应用智能优化"""
        # 优化1：自动无人机能量管理
        self._optimize_drone_energy_management(white_boats, white_drones, current_time)
        
        # 优化2：自动避免无效移动
        self._optimize_movement_efficiency(white_boats, dt)
    
    def _optimize_drone_energy_management(self, white_boats: List['WhiteBoat'], 
                                        white_drones: List['WhiteDrone'], current_time: float):
        """优化无人机能量管理"""
        for drone in white_drones:
            if drone.state == "flying" and drone.energy < 15.0:  # 低电量时自动返航
                if drone.state != "returning":
                    drone.state = "returning"
                    if self.debug_mode:
                        print(f"[SmartExecutor] 无人机{drone.id}自动返航，电量:{drone.energy:.1f}%")
    
    def _optimize_movement_efficiency(self, white_boats: List['WhiteBoat'], dt: float):
        """优化移动效率"""
        for boat in white_boats:
            if not boat.active:
                continue
            
            # 检查是否在做无效的微小移动
            if boat.speed < 0.5:  # 速度过慢时停止移动
                boat.speed = 0
    
    def _update_performance_tracking(self, white_boats: List['WhiteBoat'], 
                                   white_drones: List['WhiteDrone'], current_time: float):
        """更新性能追踪"""
        # 统计当前状态
        active_boats = sum(1 for boat in white_boats if boat.active)
        flying_drones = sum(1 for drone in white_drones if drone.state == "flying")
        
        self.performance_tracker[current_time] = {
            'active_boats': active_boats,
            'flying_drones': flying_drones,
            'total_actions': len(self.action_history)
        }
    
    def get_performance_stats(self) -> dict:
        """获取性能统计"""
        if not self.performance_tracker:
            return {}
        
        recent_data = list(self.performance_tracker.values())[-10:]  # 最近10次记录
        
        return {
            'avg_active_boats': sum(d['active_boats'] for d in recent_data) / len(recent_data),
            'avg_flying_drones': sum(d['flying_drones'] for d in recent_data) / len(recent_data),
            'total_actions_executed': len(self.action_history)
        } 